﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using SimulationPresenter.Presentation.Helpers;

namespace SimulationPresenter.Presentation.Primitives
{
    public class BoxShape : IPresentationPrimitive
    {
        private BoxDescriptor descriptor;

        public bool Visible
        {
            get; set;
        }

        public Vector3 Position
        {
            get
            {
                return descriptor.Position;
            }

            set
            {
                descriptor.Position = value;
            }
        }

        public float Size
        {
            get
            {
                return descriptor.Size;
            }
        }

        private Color color;

        //Todo: Think of moving Color property to helper (somehow)
        public Color Color
        {
            get
            {
                return color;
            }
            set
            {
                color = value;
                Recolor();
            }
        }

        public short[] Indices
        {
            //Todo: Check Counterclockwiseness of BoxShape
            get
            {
                return new short[]
                           {
                               //1
                               3, 0, 1,
                               1, 2, 3,
                               //2
                               2, 1, 5,
                               5, 6, 2,
                               //3
                               6, 5, 4,
                               4, 7, 6,
                               //4
                               7, 4, 0,
                               0, 3, 7,
                               //5
                               0, 4, 5,
                               5, 1, 0,
                               //6
                               7, 3, 2,
                               2, 6, 7
                           };
            }
        }

        public BoxShape(float size, Vector3 position)
        {
            Visible = true;

            descriptor = new BoxDescriptor
                                   {
                                       Size = size,
                                       Position = position
                                   };

            RebuildBox();
            Color = Color.DarkOrange;

            //Must use "this" since it's a helper function
            Recolor();
        }

        private void Recolor()
        {
            if (null != VerticesWithNormal)
            {
                for (int i = 0; i < VerticesWithNormal.Length; i++)
                {
                    VerticesWithNormal[i].Color = Color.ToArgb();
                } 
            }
        }

        /// <summary>
        /// Regenerates Vertices matrix
        /// </summary>
        private void RebuildBox()
        {
            VerticesWithNormal = new CustomVertex.PositionNormalColored[8];

            VerticesWithNormal[0].Position = new Vector3(-descriptor.HalfSize,
                                                descriptor.HalfSize,
                                                -descriptor.HalfSize);
            VerticesWithNormal[0].Normal = new Vector3(-1,
                                                1,
                                                -1);
            VerticesWithNormal[1].Position = new Vector3(descriptor.HalfSize,
                                                descriptor.HalfSize,
                                                -descriptor.HalfSize);
            VerticesWithNormal[1].Normal = new Vector3(1,
                                                1,
                                                -1);
            VerticesWithNormal[2].Position = new Vector3(descriptor.HalfSize,
                                                -descriptor.HalfSize,
                                                -descriptor.HalfSize);
            VerticesWithNormal[2].Normal = new Vector3(1,
                                                -1,
                                                -1);
            VerticesWithNormal[3].Position = new Vector3(-descriptor.HalfSize,
                                                -descriptor.HalfSize,
                                                -descriptor.HalfSize);
            VerticesWithNormal[3].Normal = new Vector3(-1,
                                                -1,
                                                -1);
            VerticesWithNormal[4].Position = new Vector3(-descriptor.HalfSize,
                                                descriptor.HalfSize,
                                                descriptor.HalfSize);
            VerticesWithNormal[4].Normal = new Vector3(-1,
                                                1,
                                                1);
            VerticesWithNormal[5].Position = new Vector3(descriptor.HalfSize,
                                                descriptor.HalfSize,
                                                descriptor.HalfSize);
            VerticesWithNormal[5].Normal = new Vector3(1,
                                                1,
                                                1);
            VerticesWithNormal[6].Position = new Vector3(descriptor.HalfSize,
                                                -descriptor.HalfSize,
                                                descriptor.HalfSize);
            VerticesWithNormal[6].Normal = new Vector3(1,
                                                -1,
                                                1); ;
            VerticesWithNormal[7].Position = new Vector3(-descriptor.HalfSize,
                                                -descriptor.HalfSize,
                                                descriptor.HalfSize);
            VerticesWithNormal[7].Normal = new Vector3(-1,
                                                -1,
                                                1); ;
        }
        
        /// <summary>
        /// Moves box to given position
        /// </summary>
        /// <param name="newPosition"></param>
        public void MoveTo(Vector3 newPosition)
        {
            Position = newPosition;
            RebuildBox();
        }

        private class BoxDescriptor
        {
            public float Size { get; set; }
            public float HalfSize
            {
                get
                {
                    return Size/2f;
                }
            }
            public Vector3 Position { get; set; }
        }

        #region IPresentationPrimitive Members


        public CustomVertex.PositionNormalColored[] VerticesWithNormal
        {
            get; set;
        }

        #endregion

        #region IPresentationPrimitive Members

        public VertexFormats CustomVertexFormat
        {
            get
            {
                return CustomVertex.PositionNormalColored.Format;
            }
        }

        public T[] GetVertices<T>() where T : struct
        {
            return VerticesWithNormal.Cast<T>().ToArray();
        }
        #endregion

        #region IPresentationPrimitive Members


        public Vector3[] GetPositions()
        {
            return VerticesWithNormal.Select(x => x.Position).ToArray();
        }

        public Vector3[] GetPositionsWithScale()
        {
            return GetPositions();
        }

        public void SetPositions(Vector3[] vectors)
        {
            //MeshExtensions.UpdatePositions(VerticesWithNormal, vectors, (x, y) => x.Position = y);
        }

        public float scale
        {
            get { return 1.0f; }
        }

        public Material Material
        {
            get
            {
                return new Material
                           {
                               Diffuse = Color
                           };
            }
        }

        public Texture Texture
        {
            get { return null; }
        }

        #endregion

        #region IPresentationPrimitive Members


        public bool UseScale
        {
            get
            {
                return false;
            }
            set { ;}
        }

        #endregion
    }
}
